﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using ContractManager.Common.FormBase;
using DevExpress.LookAndFeel;
using DevExpress.Utils;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Controls;
using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Design;
using LogicNP.CryptoLicensing;
using Speed.Data;

namespace ContractManager.Common.Class
{
    public enum FormState
    {
        New,
        Update,
        Delete
    };

    public static class ClsVariable
    {
        #region "Define Variable"
        public static string StrSqlConnectionString = ConfigurationManager.ConnectionStrings["ContractContext"].ConnectionString;
        public static string StrTotalSqlConnectionString = ConfigurationManager.ConnectionStrings["StrTotalSqlConnectionString"]==null ? "" : ConfigurationManager.ConnectionStrings["StrTotalSqlConnectionString"].ConnectionString;
        
        public static DataTable DtParam=new DataTable();
        public static DataTable DtAction = new DataTable();
        public static DataTable DtCurrency = new DataTable();
        public static DataTable DtAccountLeaf = new DataTable();
        public static DataTable DtPayment = new DataTable();
        public static DataTable DtAccount = new DataTable();
        public static DataTable DtObjectDetail = new DataTable();
        public static DataTable DtContractDetails;
        public static DataTable DtDocumentDetails;
        public static DataTable DtRevenueDetails;
        public static DataTable DtPlanRevenueDetails;

        public static string StrServerName = StrSqlConnectionString.Split(';')[0].Replace("Data Source", "").Replace("=", "").Trim();
        public static string StrDatabaseName = StrSqlConnectionString.Split(';')[1].Replace("Initial Catalog", "").Replace("=", "").Trim();

        public static string StrActivateCode = ConfigurationManager.AppSettings["ActivateCode"];
        public static string StrValidateKey = ConfigurationManager.AppSettings["ValidationKey"];
        
        public static string StrDecisionNoRow1 = ConfigurationManager.AppSettings["DecisionNoRow1"];
        public static string StrDecisionNoRow2 = ConfigurationManager.AppSettings["DecisionNoRow2"];
        public static string StrLog = ConfigurationManager.AppSettings["Location"];

        public static string StrValidateMessage = String.Empty;
        public static string StrMessage = String.Empty;
        public static string StrCurrentPath = String.Format(@"{0}\Layout\", Directory.GetCurrentDirectory());
        public static string StrReportPath = String.Format(@"{0}\Report\", Directory.GetCurrentDirectory());

        public static Database Db;

        public static int EmployeeId = 1;
        public static int MemberBranchId = 0;
        public static int RoleNo;
        public static int AsSysMyCoYearId;//Đơn vị, năm làm việc
        public static int AsSysBillStyleId;//Loại chứng từ
        
        public static int OrderBillStyle=19;//Loai chung tu don hang
        public static int Year;
        public static string UserName;
        public static string PassWord;
        public static string FullName;
        public static string Department;
        public static bool IsEditVoucher;//Cho phép sửa chứng từ của người khác

        public static string StrMachineCode;
        public static int NumberDayUse;
        public static DateTime DateExpires;

        public static string CompanyName = "Hafic";
        public static string CompanyCode = "Hafic";

        public static bool IsLogin;
        public static int FormNo;
        public static int MethodOfPrice;
        public static string StrFormName = string.Empty;


       

        public static XtraForm FrmMain;
        public static DefaultLookAndFeel SkinManager;
        #endregion

        #region "Method"
        /// <summary>
        /// Lấy tên file không chứa đường dẫn từ tên file có đường dẫn
        /// </summary>
        /// <param name="filefullname">Tên file có đường dẫn</param>
        /// <returns></returns>
        public static string GetFileShortName(string filefullname)
        {
            int lastIndexOf = filefullname.LastIndexOf(@"\", System.StringComparison.Ordinal);
            string fileShortName = filefullname.Substring(lastIndexOf + 1, filefullname.Length - 1 - lastIndexOf);
            return fileShortName;
        }

        /// <summary>
        /// Lấy ra phần mở rộng của File
        /// </summary>
        /// <param name="strFileShortName">Tên file cần lấy</param>
        /// <returns></returns>
        public static string GetFileExtention(string strFileShortName)
        {
            int lastIndexOf = strFileShortName.LastIndexOf(@".", System.StringComparison.Ordinal);
            string strExt = strFileShortName.Substring(lastIndexOf + 1, strFileShortName.Length - 1 - lastIndexOf);
            return strExt;
        }

        /// <summary>
        /// Lấy đường dẫn ứng dụng
        /// </summary>
        /// <param name="strExecutablePath"></param>
        /// <returns></returns>
        public static string GetExecutableDir(string strExecutablePath)
        {
            int intPos = strExecutablePath.LastIndexOf(@"\", System.StringComparison.Ordinal);
            return strExecutablePath.Substring(0, intPos);
        }

        public static string Encrypt(string strString)
        {
            string strEncrypt;
            
            string plainText = strString;    // original plaintext
            const string passPhrase = "Pas5pr@se";        // can be any string
            const string saltValue = "s@1tValue";        // can be any string
            const string hashAlgorithm = "SHA1";             // can be "MD5"
            const int passwordIterations = 2;                  // can be any number
            const string initVector = "@1B2c3D4e5F6g7H8"; // must be 16 bytes
            const int keySize = 256;                // can be 192 or 128


            string cipherText = EncryptSha1(plainText,
                                                        passPhrase,
                                                        saltValue,
                                                        hashAlgorithm,
                                                        passwordIterations,
                                                        initVector,
                                                        keySize);
            strEncrypt = cipherText;
            return strEncrypt;
        }


        public static string Decrypt(string strEncryptString)
        {
            string strDecrypt;
            string plainText = strEncryptString;    // original plaintext
            const string passPhrase = "Pas5pr@se";        // can be any string
            const string saltValue = "s@1tValue";        // can be any string
            const string hashAlgorithm = "SHA1";             // can be "MD5"
            const int passwordIterations = 2;                  // can be any number
            const string initVector = "@1B2c3D4e5F6g7H8"; // must be 16 bytes
            const int keySize = 256;                // can be 192 or 128



            string cipherText = DecryptSha1(plainText,
                                                        passPhrase,
                                                        saltValue,
                                                        hashAlgorithm,
                                                        passwordIterations,
                                                        initVector,
                                                        keySize);
            strDecrypt = cipherText;
            return strDecrypt;
        }



        public static string EncryptSha1(string plainText,
                                     string passPhrase,
                                     string saltValue,
                                     string hashAlgorithm,
                                     int passwordIterations,
                                     string initVector,
                                     int keySize)
        {

            byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
            byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);


            byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);


            PasswordDeriveBytes password = new PasswordDeriveBytes(
                                                            passPhrase,
                                                            saltValueBytes,
                                                            hashAlgorithm,
                                                            passwordIterations);

            byte[] keyBytes = password.GetBytes(keySize / 8);
            RijndaelManaged symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC };
            ICryptoTransform encryptor = symmetricKey.CreateEncryptor(
                                                             keyBytes,
                                                             initVectorBytes);


            MemoryStream memoryStream = new MemoryStream();

            CryptoStream cryptoStream = new CryptoStream(memoryStream,
                                                         encryptor,
                                                         CryptoStreamMode.Write);

            cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);


            cryptoStream.FlushFinalBlock();


            byte[] cipherTextBytes = memoryStream.ToArray();


            memoryStream.Close();
            cryptoStream.Close();


            string cipherText = Convert.ToBase64String(cipherTextBytes);


            return cipherText;
        }


        public static string DecryptSha1(string cipherText,
                                     string passPhrase,
                                     string saltValue,
                                     string hashAlgorithm,
                                     int passwordIterations,
                                     string initVector,
                                     int keySize)
        {

            byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
            byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);


            byte[] cipherTextBytes = Convert.FromBase64String(cipherText);


            PasswordDeriveBytes password = new PasswordDeriveBytes(
                                                            passPhrase,
                                                            saltValueBytes,
                                                            hashAlgorithm,
                                                            passwordIterations);


            byte[] keyBytes = password.GetBytes(keySize / 8);


            RijndaelManaged symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC };


            ICryptoTransform decryptor = symmetricKey.CreateDecryptor(
                                                             keyBytes,
                                                             initVectorBytes);


            MemoryStream memoryStream = new MemoryStream(cipherTextBytes);


            CryptoStream cryptoStream = new CryptoStream(memoryStream,
                                                          decryptor,
                                                          CryptoStreamMode.Read);


            byte[] plainTextBytes = new byte[cipherTextBytes.Length];

            // Start decrypting.
            int decryptedByteCount = cryptoStream.Read(plainTextBytes,
                                                       0,
                                                       plainTextBytes.Length);


            memoryStream.Close();
            cryptoStream.Close();


            string plainText = Encoding.UTF8.GetString(plainTextBytes,
                                                       0,
                                                       decryptedByteCount);


            return plainText;
        }



        #endregion

        #region " Method of XtraGrid"
        public static void ShowDesignXtraGrid(GridControl grid)
        {
            frmDesigner design = new frmDesigner();
            design.InitGrid(grid);
            design.ShowDialog();
        }

        public static bool IsSelectAllComboBoxEdit(CheckedComboBoxEdit edit)
        {
            return edit.Properties.Items.Cast<CheckedListBoxItem>().All(item => item.CheckState == System.Windows.Forms.CheckState.Checked);
        }

        public static void SetComboboxEditSelectAll(CheckedComboBoxEdit edit)
        {
            foreach (CheckedListBoxItem item in edit.Properties.Items)
	        {
		        item.CheckState = CheckState.Checked;
	        }
        }
        

        public static string GetRestoreLayoutFullPath(string fileName)
        {
            return String.Format(@"{0}{1}", StrCurrentPath, fileName);
        }

        public static string GetReportFullPath(string fileName)
        {
            return String.Format(@"{0}{1}.mrt", StrReportPath, fileName);
        }
        #endregion

        #region "Check License"

        public static bool CheckLicense(string licenseCode, ref string strError)
        {
            bool ret=true;
            const string validationKey = "AMAAMADQnPuE0ydn1CCAqrdCSOdI3JMM8mh+h9fe1wqFu7QAx4IOgLkPUkYT+kR0/OEwUwMDAAEAAQ==";
            CustomCryptoLicense license = new CustomCryptoLicense() { ValidationKey = validationKey, LicenseCode = licenseCode };
            ClsVariable.StrMachineCode = license.GetLocalMachineCodeAsString(); 
            //If Trial
            if (license.Status != LicenseStatus.Valid)
            {
                FrmMachineCode frmCode = new FrmMachineCode();
                frmCode.ShowDialog();
                strError = "Mã kích hoạt không hợp lệ.";
                ret = false;
            }
            else if (license.IsEvaluationLicense())
            {
                ClsVariable.DateExpires = license.DateLastUsed;
                ClsVariable.NumberDayUse = license.RemainingUsageDays;

                if (license.IsEvaluationExpired())
                {
                     strError = "Mã kích hoạt đã hết hạn.";
                    ret = false;
                }
            }
            else//Not Trial
            {
                string machineCode = license.MachineCodeAsString;
                string localMachineCode = license.GetLocalMachineCodeAsString();
                if (!machineCode.Equals(localMachineCode))
                {
                    strError = "Mã máy không thể xác thực với " + licenseCode;
                    ret = false;
                }
            }
            return ret;
        }

        public static void EncryptConnectionString(bool encrypt)
        {
            Configuration configuration = null;
            try
            {
                // Open the configuration file and retrieve the connectionStrings section.
                configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                ConnectionStringsSection configSection =
                configuration.GetSection("connectionStrings") as ConnectionStringsSection;
                if ((!(configSection.ElementInformation.IsLocked)) &&
                    (!(configSection.SectionInformation.IsLocked)))
                {
                    if (encrypt && !configSection.SectionInformation.IsProtected)
                    {
                        //this line will encrypt the file
                        configSection.SectionInformation.ProtectSection
                            ("DataProtectionConfigurationProvider");
                    }

                    if (!encrypt &&
                    configSection.SectionInformation.IsProtected)//encrypt is true so encrypt
                    {
                        //this line will decrypt the file. 
                        configSection.SectionInformation.UnprotectSection();
                    }
                    //re-save the configuration file section
                    configSection.SectionInformation.ForceSave = true;

                    configuration.Save();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
        #endregion

        #region "Create Wait Form"

        private static WaitDialogForm _dialogForm;
        public static string StrCaption = "Nạp dữ liệu....";

        public static void CreateWaitDialog(string caption, string title = "")
        {
            _dialogForm = String.IsNullOrEmpty(title) ? new WaitDialogForm(caption) : new WaitDialogForm(caption, title);
        }

        public static void CloseWaitDialog()
        {
            if (_dialogForm!=null) _dialogForm.Close();
        }

        public static void SetWaitDialogCaption(string fCaption)
        {
            if (_dialogForm != null) _dialogForm.Caption = fCaption;
        }

        public static void ShowMessage(string message)
        {
            MessageBox.Show(message);
        }
        
        public static string ConvertNumberToWord(decimal value)
        {
            NumberToText number = new NumberToText();
            return number.Parse(value);
        }

        public static void DoubleBuffered(this Control control, bool setting)
        {
            Type dgvType = control.GetType();
            PropertyInfo pi = dgvType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
            pi.SetValue(control, setting, null);
        }

        public static void DoubleBuffer(Control control)
        {
            control.DoubleBuffered(true);
            foreach (Control c in control.Controls) { DoubleBuffer(c); }
            
        }
        #endregion

        #region "Apply Param for Report"
        public static void ApplyReportParam(Stimulsoft.Report.StiReport report, DataTable dtParam)
        {
            dtParam.BeginLoadData();
            foreach (DataRow row in dtParam.Rows)
            {
                string paraCode = String.Format("{0}", row["ReportParamCode"]);
                string paraName = String.Format("{0}", row["ReportParamName"]);

                if (paraCode.Contains("SYSUSER"))
                {
                    report[paraCode] = ClsVariable.FullName;
                }
                else if (report.Dictionary.Variables.Contains(paraCode))
                {
                    report[paraCode] = paraName;
                }
            }
            dtParam.EndLoadData();
        }

        public static void ApplyObjectDetailParam(Stimulsoft.Report.StiReport report, DataTable dtParam)
        {
            dtParam.BeginLoadData();
            foreach (DataRow row in dtParam.Rows)
            {
                foreach (DataColumn column in dtParam.Columns)
                {
                    string paraCode = String.Format("{0}", column.ColumnName);
                    string paraName = String.Format("{0}", row[column.ColumnName]);
                    if (report.Dictionary.Variables.Contains(paraCode))
                    {
                        report[paraCode] = paraName;
                    }
                }
                
                
            }
            dtParam.EndLoadData();
        }
        #endregion

        #region "Check Log"
        private static readonly string[] VietNamChar = new string[] 
        { 
            "aAeEoOuUiIdDyY", 
            "áàạảãâấầậẩẫăắằặẳẵ", 
            "ÁÀẠẢÃÂẤẦẬẨẪĂẮẰẶẲẴ", 
            "éèẹẻẽêếềệểễ", 
            "ÉÈẸẺẼÊẾỀỆỂỄ", 
            "óòọỏõôốồộổỗơớờợởỡ", 
            "ÓÒỌỎÕÔỐỒỘỔỖƠỚỜỢỞỠ", 
            "úùụủũưứừựửữ", 
            "ÚÙỤỦŨƯỨỪỰỬỮ", 
            "íìịỉĩ", 
            "ÍÌỊỈĨ", 
            "đ", 
            "Đ", 
            "ýỳỵỷỹ", 
            "ÝỲỴỶỸ" 
        };
        public static string LocDau(string str)
        {
            //Thay thế và lọc dấu từng char      
            for (int i = 1; i < VietNamChar.Length; i++)
            {
                for (int j = 0; j < VietNamChar[i].Length; j++)
                    str = str.Replace(VietNamChar[i][j], VietNamChar[0][i - 1]);
            }
            return str;
        }
        #endregion

        #region "Infix to Postfix"
        public static bool IsValid(string input)
        {
           Regex operators = new Regex(@"[\-+*/%]", RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled);
           if (string.IsNullOrEmpty(input))
              return false;

           if (input.ToCharArray().Select(c => c == '(').Count() != input.ToCharArray().Select(c => c == ')').Count())
              return false;

           string tempString = operators.Replace(input, ".");

           if (tempString.EndsWith("."))
              return false;

           string[] contains = new string[] { "(.)", "()", "..", ".)" };

           if (contains.Any(s => tempString.Contains(s)))
           {
               return false;
           }

           operators = new Regex(@"[().]", RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled);
           tempString = operators.Replace(tempString, string.Empty);

           if (tempString.ToCharArray().Any(c => !Char.IsNumber(c)))
           {
               return false;
           }

           if (input.Contains("."))
              return false;

           tempString = input;

           operators = new Regex(@"[1234567890]", RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled);
           tempString = operators.Replace(tempString, ".");

           if (tempString.Contains(".."))
              return false;
           if (input.StartsWith("*") || input.StartsWith("/") || input.StartsWith("%") 
                                                     || input.StartsWith("+") || input.StartsWith("-"))
              return false;

           contains = new string[] {"(%","(/","(*","*","(+","(-" };
           if (contains.Any(input.Contains))
           {
               return false;
           }

           int begin = 0, end = 0;
           foreach (char c in input)
           {
              if (c == '(')
                 begin++;
              if (c == ')')
                 end++;
              if (end > begin)
                 return false;
            }
            return true;
        }

        private static bool Predecessor(char firstOperator, char secondOperator)
        {
            const string opString = "(+-*/%";

            int[] precedence = { 0, 12, 12, 13, 13, 13 };// "(" has less prececence

            int firstPoint = opString.IndexOf(firstOperator);
            int secondPoint = opString.IndexOf(secondOperator);

            return (precedence[firstPoint] >= precedence[secondPoint]);
        }

        public static string ConvertToPostFix(string inFix)
        {
            StringBuilder postFix = new StringBuilder();
            char arrival;
            Stack<char> oprerator = new Stack<char>();//Creates a new Stack
            foreach (char c in inFix.ToCharArray())//Iterates characters in inFix
            {
                if (Char.IsNumber(c))
                    postFix.Append(c);
                else if (c == '(')
                    oprerator.Push(c);
                else if (c == ')')//Removes all previous elements from Stack and puts them in 
                //front of PostFix.  
                {
                    arrival = oprerator.Pop();
                    while (arrival != '(')
                    {
                        postFix.Append(arrival);
                        arrival = oprerator.Pop();
                    }
                }
                else
                {
                    if (oprerator.Count != 0 && Predecessor(oprerator.Peek(), c))//If find an operator
                    {
                        arrival = oprerator.Pop();
                        while (Predecessor(arrival, c))
                        {
                            postFix.Append(arrival);

                            if (oprerator.Count == 0)
                                break;

                            arrival = oprerator.Pop();
                        }
                        oprerator.Push(c);
                    }
                    else
                        oprerator.Push(c);//If Stack is empty or the operator has precedence 
                }
            }
            while (oprerator.Count > 0)
            {
                arrival = oprerator.Pop();
                postFix.Append(arrival);
            }
            return postFix.ToString();
        }
        #endregion
    }
       


    /// <summary>
    /// Lop doi so ra chu
    /// </summary>
    public class NumberToText
    {
        #region Names

        /// <summary>
        /// alternative name of Five
        /// </summary>
        protected string MAltFive = "lăm";

        /// <summary>
        /// alternative name of One
        /// </summary>
        protected string MAltOne = "mốt";

        /// <summary>
        /// name of simple number digit
        /// </summary>
        protected string[] MDigits = new string[]
                                         {
                                             "không", "một", "hai", "ba", "bốn", "năm", "sáu", "bảy", "tám", "chín", "mười"
                                         };

        /// <summary>
        /// Name of digit groups
        /// </summary>
        protected string[] MGroups = new string[]
                                         {
                                             "trăm", "ngàn", "triệu", "tỉ", "ngàn tỉ", "triệu tỉ", "tỉ tỉ", "ngàn tỉ tỉ",
                                             "triệu tỉ tỉ", "tỉ tỉ tỉ"
                                         };

        /// <summary>
        /// name of negative sign
        /// </summary>
        protected string MNegative = "trừ";

        /// <summary>
        /// postfix for tens
        /// </summary>
        protected string MTenPostfix = "mươi";

        /// <summary>
        /// name of single sequence digit (linh, lẻ)
        /// </summary>
        protected string MZeroSequence = "lẻ";

        #region Unit Name

        private string _mUnitName = "đồng";

        /// <summary>
        /// Gets/Sets name of unit
        /// </summary>
        public string UnitName
        {
            get { return _mUnitName; }
            set { _mUnitName = value; }
        }

        #endregion

        #endregion

        #region Build group

        private bool _useZeroHundred;

        /// <summary>
        /// Build name of a group (expected value: [0, 999]
        /// </summary>
        protected virtual string BuildGroup(int value)
        {
            StringBuilder result = new StringBuilder();
            bool useAlt = false;
            bool zeroTen = false;
            bool zeroHundred = false;
            //build hundred
            int digit = value / 100;
            if (_useZeroHundred || (digit != 0))
            {
                result.Append(String.Format("{0} {1}", MDigits[digit], MGroups[0]));
            }
            zeroHundred = digit == 0;
            //build ten
            digit = value % 100 / 10;
            if (digit == 0) zeroTen = true;
            else
            {
                if (digit == 1) result.Append(" " + MDigits[10]);
                else result.Append(String.Format(" {0} {1}", MDigits[digit], MTenPostfix));
            }
            useAlt = (digit != 0) && (digit != 1);
            //build unit
            digit = value % 10;
            if ((digit != 0) && zeroTen)
            {
                if (zeroHundred)
                {
                    if (_useZeroHundred) result.Append(String.Format(" {0} {1}", MZeroSequence, MDigits[digit]));
                    else result.Append(" " + MDigits[digit]);
                }
                else
                {
                    result.Append(String.Format(" {0} {1}", MZeroSequence, MDigits[digit]));
                }
            }
            else if (digit == 1)
            {
                if (useAlt) result.Append(" " + MAltOne);
                else result.Append(" " + MDigits[1]);
            }
            else if (digit == 5)
            {
                if (zeroTen) result.Append(" " + MDigits[5]);
                else result.Append(" " + MAltFive);
            }
            else if (digit != 0) result.Append(" " + MDigits[digit]);
            return result.ToString();
        }

        #endregion

        #region Get Group Name

        /// <summary>
        /// Build group's name based on the power of group
        /// </summary>
        private string GetGroupName(int power)
        {
            string result = "";
            int idx = power / 3;
            if ((idx > 0) && (idx < MGroups.Length)) result = MGroups[idx];
            //else if (idx > 0) result = GetGroupName(idx) + " " + mGroups[3];
            return result;
        }

        #endregion

        #region Parse

        /// <summary>
        /// Converts a number to words
        /// </summary>
        public virtual string Parse(double value)
        {
            string result = "";
            StringBuilder sb = new StringBuilder();
            if (value == 0) result = String.Format("{0} {1}", MDigits[0], _mUnitName);
            else
            {
                if (value < 0)
                {
                    result = MNegative + " ";
                    value = -value;
                }
                int length = (int)Math.Log10(value);
                _useZeroHundred = false;
                while (length >= 0)
                {
                    int groupLength = length;
                    while (groupLength % 3 != 0) groupLength--;
                    int group = (int)(value / Math.Pow(10, groupLength));
                    if (group > 0)
                    {
                        sb.Append(BuildGroup(group));
                        sb.Append(String.Format(" {0} ", GetGroupName(length)));
                    }
                    string tmp = sb.ToString();
                    //prepare for next group
                    value = value - group * Math.Pow(10, groupLength);
                    length -= 3;
                    _useZeroHundred = true;
                } //while length > 0  
                result += String.Format("{0} {1}", sb.ToString().Trim(), _mUnitName);
            }

            return result;
        }

        /// <summary>
        /// Converts a number to words
        /// </summary>
        public virtual string Parse(decimal value)
        {
            return Parse((double)value);
        }

        /// <summary>
        /// Converts a number to words
        /// </summary>
        public virtual string Parse(int value)
        {
            return Parse(value);
        }

        #endregion

        #region Constructors

        #endregion
    }
}
